package edu.psu.geovista.app.plot.axis;

//import edu.psu.geovista.app.pcp.tools.Coordinate2D;
//import edu.psu.geovista.app.pcp.tools.CoordinateTransform;

import edu.psu.geovista.app.plot.ruler.Ruler;
import edu.psu.geovista.classification.CategoryList;

import java.awt.*;

/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * All Rights Researved.
 *
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * Description
 * Functions
 *      - used by plot
 * There are two sets of origins and sizes: total = the entire rectangle taken up by this axis,
 * and active = the area in use as "real" number space mapping
 *
 *  total -> +----+             -
 *  origin   |    |             ^
 *  active ->+----+ -
 *  origin   |    | ^
 *           |    |
 *           |    |
 *           | .. |  active size
 *           |    |
 *           |    |            total size
 *           |    | v
 *           +----+ -
 *           |    |             v
 *           +----+             -
 *
 * Date: May 29, 2003
 * Time: 11:13:54 AM
 * @author Jin Chen
 */

public class YAxis extends BasicAxis implements Comparable {
    public  static final int PAINT_MODE_SIMPLE =1 ;
    public static final int PAINT_MODE_FULL=2;

    public static final String DTYPE_Qty="Qty"; // 
    public static final String DTYPE_Ord="Ord";// 
    public static final String DTYPE_Nml="Nml";// 

    public static final boolean DEBUG=false;
    public static final int FOOTER_PAD=5; //offset between axis's bottom and start point of footer
    public static final int HEADER_PAD=20; //offset between axis's top and start point of header
     /*private static final String uiClassID = "YAxisUI";

    static {//register PcpUI
        // UIManager.put(<UI Class ID>, <UI Class's full package name>");

        UIManager.put("BasicAxisUI", "edu.psu.geovista.app.plot.axis.YAxisUI");
    }*/
    //Logic
    /**
     * y0 is  the  real y value that on the O point of drawing coordinate.
     * By default, it is max of tickRange.max. If make axis up side down, the y0=tickRange.min
     */
    //private float valueAt0;   //ypixel= =y0 *ks - RawY*ks
    //float ks=1;//scale for mapping data display range to axis display range. By default, do not scale(ks=1)
    protected int index;  //display Index
    protected int dataIndex;//map to the data column the axis represent
    //GUI
    protected String DisplayType=DTYPE_Nml;
    protected boolean movable;
    protected boolean selected;// if selected, the YAxis's root change from a rect boundary to  a filled rectangle
    protected boolean showDescription;
    private boolean showHeader=true;
    private boolean showFooter=true;


    //protected int axisGap;//gap between current aixs and previous one
    protected float columnValue;   //for time series

    private boolean boxPlotShown;

    //Components
    //Need to put following in UI later
    private AxisYHeader header;
    private AxisYFooter footer;
    private BoxPlot boxplot;



    public YAxis() {
    }

    public YAxis(int activeSize,Point axisLoc, Range dataRange, String axisName, int rawIndex, CategoryList categoryList) {
        super(Ruler.VERTICAL, dataRange, activeSize, axisName);
        

        this.setAxisLocation(axisLoc.x,axisLoc.y);
        this.setDataIndex(rawIndex) ;
        this.setIndex(rawIndex); //by default displayIndex = rawIndex
        //ruler=new ColorRuler(this.getOrient(), activeSize, this.getAxisLocation(),dataRange );
        this.setCategoryList(categoryList);
        //this.setAxisGap(AxisLayer.AXIS_GAP );


        //if (category!=null) ruler.setCategoryColors(category.getColors());

        //header=new AxisYHeader(this.getName(),this.getLocation());//Must use this.getLocation(), thus header position change with axis changing
        header=new AxisYHeader(this);
        footer=new AxisYFooter(this);
        //this.painter =new YAxisPainter(this);

    }


   /**
    *  see if the given point is within the axis's reacting area for the mouse event
    */
    public boolean footerContain(Point p) {
       return this.footer.contain(p);
    }
    public boolean footerContain(int x, int y) {
       return this.footer.contain(x, y);
    }
    public boolean headerContain(int x, int y) {
       return this.header.contain(x, y);
    }
    /**
     *  
     *  
     * @param x
     * @param y
     * @return
     */
    public boolean isDescriptionAreaContain(int x,int y){
          return headerContain(x,y);
    }

    /********************************************************************
     *               DATA Functionalities
     ********************************************************************/

     public int transform(float realy){

        int pixely=Math.round(getGraphicValueOf(realy));
        return pixely;
     }



    /*******************************************************************************************************
     *                Position placement
     *******************************************************************************************************/
    public float getColumnValue() {
        return columnValue;
    }

    public void setColumnValue(float columnValue) {
        this.columnValue = columnValue;
    }
    public String getDisplayType() {
        return DisplayType;
    }

    public void setDisplayType(String displayType) {
        DisplayType = displayType;
    }
    /**
     *
     * @return  true, the axis can be moved horizontally within some range.
     *                The method doesn't consider the range issue
     */
    public boolean isMovable() {
       if(this.getDisplayType() ==DTYPE_Qty){
           return false;
       }
       return true;
    }

    public void setMovable(boolean movable) {
        this.movable = movable;
    }

    /********************************************************************
     *                paint
     ********************************************************************/

    public void paintComponent(Graphics g){
        //super.setUI(this.ruler ) ;
        if(this.isVisible() ){
            //System.out.println("paint "+getName() + " index "+getIndex() + " loc :"+getLocation().x);

            super.paintComponent(g);
            if(this.isBoxPlotShown() )
                this.boxplot.paintComponent(g,this);
            if(this.isShowHeader())
                this.header.paintComponent(g);
            if(this.isShowFooter())
                this.footer.paintComponent(g);
        }
         //this.painter.paintComponent(g);

    }

    public void setPaintMode(int mode){
        if(mode==PAINT_MODE_SIMPLE){
            Ruler ruler = this.getRuler();
            ruler.setShowTick(false);
            

        }
        else if(mode==PAINT_MODE_FULL){
            Ruler ruler = this.getRuler();
            ruler.setShowTick(true);

        }
        this.header.setPaintmode(mode);
        this.footer.setPaintmode(mode);
    }

    /********************************************************************
     *                Properties
     ********************************************************************/
    public boolean isBoxPlotShown() {
        return boxPlotShown;
    }

    public void setBoxPlotShown(boolean boxPlotShown) {
        this.boxPlotShown = boxPlotShown;
    }


     public void setBoxplot(BoxPlot boxplot) {
        this.boxplot = boxplot;
    }

    public BoxPlot getBoxplot() {
        return boxplot;
    }

    public void setAsDefaultRanges(Range ex){
         this.setDataRange(ex);
         this.setTickRange(ex);
         this.setShowRange(ex);
    }
    public int compareTo(Object o) {
        YAxis another=(YAxis)o;
        if (this.getIndex() <another.getIndex() ){
            return -1;
        }
        else if  (this.getIndex() >another.getIndex() ){
            return 1;
        }
        else{
                return 0;
        }
    }


    /**
     *
     * @return display index
     */
    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        //Point newLoc=AxisLayer.calculateAxisPosition(index);
        //setLocation(newLoc.x, newLoc.y);
    }

    /**
     *
     * @return index of the data column the axis represent
     */
    public int getDataIndex() {
        return dataIndex;
    }

    public void setDataIndex(int dataIndex) {
        this.dataIndex = dataIndex;
    }
    public Dimension getSize(){
        return super.getSize();// 
    }

    public Dimension getTotalSize(){
         Dimension hsize = header.getSize();
        Dimension fsize = footer.getSize();

        int h=hsize.height +this.getActiveSize()+fsize.height ;
        int w;
        if(hsize.width >=fsize.width ){
            w=hsize.width ;
        }
        else{
            w=fsize.width ;
        }
        // Dimension size=super.getSize() ;
        //System.out.println("getSize()-----------------------------------"+size);
        return new Dimension(w,h);
    }

    /*public int getAxisGap() {
        return axisGap;
    }*/

    public boolean isSelected() {
        return this.footer.isFilledShape() ;
    }

    public void setSelected(boolean selected) {
       this.footer.setFilledShape(selected);
    }

    public boolean isShowDescription() {
        return showDescription;
    }

    public void setShowDescription(boolean showDescription) {
        this.showDescription = showDescription;
    }

    public CategoryList getCategoryList() {
        return this.getModel().getCategoryList() ;
    }

    public void setCategoryList(CategoryList categoryList) {
        //this.category = category;

        //if (categoryList!=null){
            this.getModel().setCategoryList(categoryList);
            //ruler.setCategoryColors(category.getColors());
            //footer.setColors(category.getColors());
            //footer.setTitle(category.getCategoryMethodName());
        //}

    }

    public AxisYFooter getFooter() {
        return footer;
    }

    public String toString(){
        return getClass().getName()+"@"+Integer.toHexString(this.hashCode() );
    }
    public  YAxis cloneConfigAxis(){
        YAxis configee=new YAxis();
        //for range configuration
        configee.setDataRange(getDataRange() );
        configee.setTickRange(this.getTickRange() );
        configee.setShowRange(this.getShowRange() );
        configee.setName( this.getName());
        return configee;
    }

    public void setHeaderFont(Font font){
        this.header.setFont(font);
    }
    public void setShowLabel(boolean showLabel) {
        edu.psu.geovista.app.plot.ruler.Ruler ruler=((BasicAxisUI)this.getUI()).getRuler() ; //??? not YAxisUI , otherwise => cast exception
        ruler.setShowLabel(showLabel);
       // ruler.setDrawTick(showLabel);
    }
     public void setLabelScale(int labelScale) {
        super.setLabelScale(labelScale);
        this.boxplot.setLabelScale(labelScale);

    }

    public boolean isShowHeader() {
        return showHeader;
    }

    public void setShowHeader(boolean showHeader) {
        this.showHeader = showHeader;
    }

    public boolean isShowFooter() {
        return showFooter;
    }

    public void setShowFooter(boolean showFooter) {
        this.showFooter = showFooter;
    }

    

    public AxisYHeader getHeader() {
        return header;
    }

}

